package com.javabasic2.pjchatserver;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Random;
import java.util.logging.LogManager;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import com.javabasic2.packet.*;

public class ChatFrame extends JFrame implements ActionListener {

	private JPanel commandPanel, messagePanel;
	private JTextArea messageList;
	private JTextField message;
	private JButton startButton, stopButton, sendButton;
	private Object key = new Object();
	private ListeningThread listener;
	private LinkedList<NetUnit> clients;
	private PJChatPacket packet;
	private Question quest;
	private String result;
	private int examinerNumber;
	private int examinerCount;
	private boolean gameStartCheck = false;

	public ChatFrame() {
		examinerCount = 0;
		examinerNumber = 0;
		packet = new PJChatPacket();
		quest = new Question();
		init();
	}
	public LinkedList<NetUnit> getClients() {
		return clients;
	}
	public void addClient(NetUnit unit) {
		synchronized (key) {
			clients.add(unit);
		}
	}
	//마우스이벤트
	public void actionPerformed(ActionEvent e) {
		JButton button = (JButton) e.getSource();
		String title = button.getText();
		if (title.equals("서버 시작")) {
			listener = new ListeningThread(this);
			listener.start();
			toggleControlState(true);
			logMessage("***** 서버가 시작 되었습니다. *****");
		} else if (title.equals("서버 중지")) {
			listener.doStop();
			disconnectAllClient();
			toggleControlState(false);
			logMessage("***** 서버가 중지 되었습니다. *****");
		} else if (title.equals("전송")) {
		}
	}
	//메세지 전송 관련
	public void logMessage(String message) {
		messageList.append(message);
		messageList.append("\n");
	}

	private void toggleControlState(boolean started) {
		startButton.setEnabled(!started);
		stopButton.setEnabled(started);
		message.setEditable(started);
		sendButton.setEnabled(started);
	}
	//게임도중 새로운 클라이언트 접속시 기존의 그린 데이터를 새로운 클라이언트가 받는다.
	public void loadArrayList(){ 
		int i = examinerCount;
		NetUnit client = clients.get(i);
		PJChatPacket tempPacket = new PJChatPacket();
		tempPacket.setType("exportPoint");
		client.doSend(tempPacket);
		
		
	}
	//게임문제 process
	public void questCheck() {
		synchronized (key) {
			if (clients.size() > 1) {// 1명이상일시 문제출제
				gameStartCheck = true;
				if (!(examinerCount < clients.size()))
					examinerCount = 0;
				for (int i = 0; i < clients.size(); i++) {
					NetUnit client = clients.get(i);
					if (examinerCount == i) {
						if (client.isRunning()) {
							Random random = new Random();
							int num = random.nextInt(15) + 0;
							result = quest.getRandomQuestion(num);
							PJChatPacket tempPacket = new PJChatPacket();
							tempPacket.setNumber(i);
							tempPacket.setId(client.getUnitName());
							tempPacket.setType("question");
							tempPacket.setData(result);
							tempPacket.setTrueORfalse(true);
							client.doSend(tempPacket);
							//
							PJChatPacket tempPacket1 = new PJChatPacket();
							String data2 = "null~~~~~";
							tempPacket1.setNumber(i);
							tempPacket1.setId(client.getUnitName());
							tempPacket1.setType("question");
							tempPacket1.setData(data2);
							tempPacket1.setTrueORfalse(false);
							broadcast(tempPacket1, client);
							break;
						} else {
							clients.remove(client);
						}
					}
				}
			} else {
				NetUnit client = clients.get(0);
				PJChatPacket tempPacket2 = new PJChatPacket();
				String data2 = "";
				tempPacket2.setNumber(5);
				tempPacket2.setId(client.getUnitName());
				tempPacket2.setType("question");
				tempPacket2.setData(data2);
				tempPacket2.setTrueORfalse(false);
				client.doSend(tempPacket2);
				examinerCount = 0;
			}
		}
	}
	// 수신 메소드(클라이언트에게 받은 데이터 처리)
	public void processMessage(NetUnit netUnit, Object packetTransfer) {
		PJChatPacket temp = (PJChatPacket) packetTransfer;
		String type = temp.getType();
		switch (type) {
		case "disconnect":
			broadcast(packetTransfer, netUnit);
			disconnectClient(netUnit);
			PJChatPacket packet3 = scoreSave(packet, netUnit);
			userStatus(packet3, netUnit);
			break;
		case "point":
			broadcast(packetTransfer, netUnit);
			break;
		case"exportPoint":
			ArrayList<PicturePacket> pd = temp.getPointList();
			PJChatPacket packet7 = new PJChatPacket();
			packet7.setType("importPoint");
			packet7.setPointList(pd);
			NetUnit unit = clients.get(clients.size()-1);
			unit.doSend(packet7);
			break;
		case "login":
			String name = temp.getId();
			int number = temp.getNumber();
			netUnit.setUnitName(name);
			netUnit.setUnitNumber(number);
			broadcast(packetTransfer, netUnit);
			if(clients.size()>2)
				loadArrayList();
			break;
		case "userCheck":
			userStatus(packetTransfer, netUnit);
			PJChatPacket packet = (PJChatPacket) packetTransfer;
			packet.setNumber(11111111);
			PJChatPacket packet2 = scoreSave(packet, netUnit);
			questCheck();
			userStatus(packet2, netUnit);
			break;
		case "changeid":
			String name1 = temp.getId();
			int number1 = temp.getNumber();
			netUnit.setUnitName(name1);
			netUnit.setUnitNumber(number1);
			broadcast(packetTransfer, netUnit);
			break;
		case "message":
			String resultCheck = (String) temp.getData();
			if (result.equals(resultCheck)) {
				PJChatPacket packet1 = scoreSave(packetTransfer, netUnit);
				examinerCount++;
				questCheck();
				userStatus(packet1, netUnit);
				PJChatPacket packet4= new PJChatPacket();
				packet4.setType("clear");
				userStatus(packet4, netUnit);
			}
			broadcast(packetTransfer, netUnit);
			break;
		default:
			broadcast(packetTransfer, netUnit);
		}
	}
	//게임 실행도중 클라이언트들이 획득한 점수 등록
	private PJChatPacket scoreSave(Object packetTransfer,NetUnit netUnit){
		PJChatPacket temp = (PJChatPacket) packetTransfer;
		int number = temp.getNumber();
		for (int i = clients.size() - 1; i >= 0; i--) {
			NetUnit client = clients.get(i);
			if (client.isRunning()) {
				if(client.getUnitNumber() == number){
					client.setScore(client.getScore()+10);
				}
			} else {
				clients.remove(client);
			}
		} 
		ArrayList<Integer> scoreList = new ArrayList<Integer>();
		for (int i = 0; i < 4; i++) {
			if(i < clients.size()){
				NetUnit client = clients.get(i);
				if (client.isRunning()) {
					scoreList.add(client.getScore());
				} else {
					clients.remove(client);
				}
			}
			else
				scoreList.add(0);
		}
		PJChatPacket packet= new PJChatPacket();
		packet.setType("reset");
		packet.setScoreList(scoreList);
		return packet;
	}
	//현재 접속된 클라이언트들에 대한 상태설정
	private void userStatus(Object packetTransfer, NetUnit from) {
		try {
			String[] userList = new String[clients.size()];
			for (int i = 0; i < clients.size(); i++) {
				NetUnit client = clients.get(i);
				if (client.isRunning()) {
					userList[i] = client.getUnitName();
				} else {
					clients.remove(client);
				}
			}
			PJChatPacket temp = (PJChatPacket) packetTransfer;
			temp.setUserList(userList);
			synchronized (key) {
				for (int i = clients.size() - 1; i >= 0; i--) {
					NetUnit client = clients.get(i);
					if (client.isRunning()) {
						client.doSend(temp);
					} else {
						clients.remove(client);
					}
				}
			}
		} catch (Exception e) {
		}
	}

	// 전송 메소드(전체)
	private void broadcast(Object packetTransfer, NetUnit from) {// 전체 메세지 송신

		synchronized (key) {
			for (int i = clients.size() - 1; i >= 0; i--) {
				NetUnit client = clients.get(i);
				if (client != from) {
					if (client.isRunning()) {
						PJChatPacket temp = (PJChatPacket) packetTransfer;
						client.doSend(packetTransfer);
					} else {
						clients.remove(client);
					}
				}
			}
		}
	}

	// 연결끊기 전송
	private void disconnectClient(NetUnit unit) {
		synchronized (key) {
			// String data = "연결종료";
			// packet.setAll(unit.getUnitNumber(),
			// unit.getUnitName(),"disconnect", data);
			unit.setScore(0);
			unit.doSend(packet);
			unit.doStop();
			clients.remove(unit);
		}
	}

	// 연결끊기 전체
	private void disconnectAllClient() {
		synchronized (key) {
			for (int i = clients.size() - 1; i >= 0; i--) {
				NetUnit client = clients.get(i);
				String data = "서버와 연결이 끊어졌습니다.";
				packet.setAll(client.getUnitNumber(), client.getUnitName(),
						"disconnect", data);
				client.doSend(packet);
				client.doStop();
				clients.remove(client);
			}
		}
	}

	private void init() {

		clients = new LinkedList<NetUnit>();

		setTitle("채팅서버");
		setSize(500, 500);
		setResizable(false);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		// 1. 상단 명령 버튼 구성 (서버시작, 서버종료)
		commandPanel = new JPanel();
		startButton = new JButton("서버 시작");
		startButton.setPreferredSize(new Dimension(150, 30));
		startButton.addActionListener(this);
		commandPanel.add(startButton);
		stopButton = new JButton("서버 중지");
		stopButton.setPreferredSize(new Dimension(150, 30));
		stopButton.setEnabled(false);
		stopButton.addActionListener(this);
		commandPanel.add(stopButton);
		add(commandPanel, BorderLayout.NORTH);

		// 2. 채팅 데이터 표시 영역 구성
		messageList = new JTextArea();
		messageList.setEditable(false);
		JScrollPane messagePane = new JScrollPane(messageList);// 스크롤 지원 컴포넌트
		add(messagePane, BorderLayout.CENTER);

		// 3. 메시지 입력 요소 구성(텍스트필드, 버튼)
		messagePanel = new JPanel();
		message = new JTextField();
		message.setPreferredSize(new Dimension(400, 30));
		message.setEditable(false);
		messagePanel.add(message);
		sendButton = new JButton("전송");
		sendButton.setPreferredSize(new Dimension(70, 30));
		sendButton.setEnabled(false);
		sendButton.addActionListener(this);
		messagePanel.add(sendButton);
		add(messagePanel, BorderLayout.SOUTH);

	}
}
